<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>cannon.js - Canvas interpolation example</title>
    <link rel="stylesheet" href="css/style.css" type="text/css" />
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
    <style>
      .page-title {
        color: black;
      }
      .page-title span {
        color: #2f56e7;
      }
    </style>
    <script type="module">
      import { addTitle, addSourceButton } from './js/dom-utils.js'

      addTitle()
      addSourceButton()
    </script>
  </head>
  <body>
    <script type="module">
      import * as CANNON from '../dist/cannon-es.js'

      /**
       * Example of interpolatedPosition and interpolatedQuaternion
       * using a canvas for simplicity
       */

      let ctx
      let world
      let sphereBody

      const radius = 1

      let lastCallTime = getTime()

      init()
      animate()

      function init() {
        // Init canvas
        const canvas = document.createElement('canvas')
        canvas.width = window.innerWidth
        canvas.height = window.innerHeight
        document.body.appendChild(canvas)

        ctx = canvas.getContext('2d')
        ctx.lineWidth = 0.05

        window.addEventListener('resize', () => {
          canvas.width = window.innerWidth
          canvas.height = window.innerHeight
          ctx.lineWidth = 0.05
        })

        // Init world
        world = new CANNON.World()

        // Add a circle (sphere) in the physics world
        const sphereShape = new CANNON.Sphere(radius)
        sphereBody = new CANNON.Body({
          mass: 1,
          position: new CANNON.Vec3(1, -2.5, 0),
        })
        sphereBody.addShape(sphereShape)
        world.addBody(sphereBody)
      }

      function drawCircles() {
        // Draw the circle at the interpolated position
        ctx.beginPath()
        ctx.arc(sphereBody.interpolatedPosition.x, sphereBody.interpolatedPosition.y, radius, 0, Math.PI * 2)
        ctx.stroke()

        // Draw the circle at the fixed step position
        ctx.beginPath()
        ctx.arc(sphereBody.position.x, sphereBody.position.y, radius, 0, Math.PI * 2)
        ctx.stroke()
      }

      function render() {
        ctx.clearRect(0, 0, window.innerWidth, window.innerHeight)
        ctx.save()
        ctx.translate(window.innerWidth / 2, window.innerHeight / 2)
        ctx.scale(50, 50)
        drawCircles()
        ctx.restore()
      }

      // Animation loop
      function animate() {
        requestAnimationFrame(animate)

        const time = getTime()

        // Compute time since last time we called the .step() method
        const timeSinceLastCall = time - lastCallTime
        lastCallTime = time

        sphereBody.velocity.x = Math.cos(time) * 3
        sphereBody.velocity.y = Math.sin(time) * 3

        // Fixed time step to use for physics. We use a huge timestep of 0.5 to see what's going on.
        // NOTE: For most games, fixedTimeStep=1/60 is a good choice.
        const fixedTimeStep = 0.5 // seconds

        // Max number of fixed physics timesteps to do in one .step(). We choose a large number to see what is going on.
        // NOTE: for most games, maxSubSteps=3 is probably a good choice.
        const maxSubSteps = 10

        // Now step the world.
        // This will do integration at a fixed time step, but compute interpolated positions
        // which are stored in body.interpolatedPosition.
        world.step(fixedTimeStep, timeSinceLastCall, maxSubSteps)

        // Render both interpolated and fixed-step positions
        render(ctx, sphereBody)
      }

      // Get current time, in seconds.
      function getTime() {
        return performance.now() / 1000
      }
    </script>
  </body>
</html>
